package erratum

import (
	"io"
)

const testVersion = 2

type TransientError struct {
	err error
}

func (e TransientError) Error() string {
	return e.err.Error()
}

type FrobError struct {
	defrobTag string
	inner     error
}

func (e FrobError) Error() string {
	return e.inner.Error()
}

type Resource interface {
	io.Closer

	Frob(string)

	Defrob(string)
}

type ResourceOpener func() (Resource, error)

func Use(o ResourceOpener, input string) (err error) {
	res, err := o()
	for err != nil {
		switch err.(type) {
		case TransientError:
			res, err = o()
		default:
			return err
		}
	}

	defer func() {
		if r := recover(); r != nil {
			switch v := r.(type) {
			case FrobError:
				res.Defrob(v.defrobTag)
				err = v
			case error:
				err = v
			}
		}

		res.Close()
	}()

	res.Frob(input)
	return
}
